namespace CSharpCLI { 

/// <summary>
/// Perform connection pooling
/// </summary>
public class ConnectionPool {
    /// <summary>
    /// Make new pooled connection. If there is unused connection to this host
    /// with the same user name and password
    /// </summary>
    /// <param name="hostAddress">string with server host name</param>
    /// <param name="hostPort">integer number with server port</param>
    ///
    public Connection newConnection(string hostAddress, int hostPort) 
    {
        lock (this) 
        { 
            return newConnection(hostAddress, hostPort, "guest", "");
        }
    }

    /// <summary>
    /// Make new pooled connection. If there is unused connection to this host
    /// with the same user name and password
    /// </summary>
    /// <param name="hostAddress">string with server host name</param>
    /// <param name="hostPort">integer number with server port</param>
    /// <param name="userName">user name</param>
    /// <param name="password">password</param>
    ///
    public Connection newConnection(string hostAddress, int hostPort, string userName, string password) 
    { 
        lock (this) 
        {
            Connection con;
            for (con = connectionChain; con != null; con = con.next) 
            {
                if (con.address.Equals(hostAddress) && con.port == hostPort &&
                    con.user.Equals(userName) && con.password.Equals(password))
                {
                    connectionChain = con.next;
                    return con;
                }
            }
            con = new Connection(this);
            con.open(hostAddress, hostPort, userName, password);
            return con;
        }
    }
    
    /// <summary>
    /// Return conection to the pool
    /// </summary>
    /// <param name="conxn">released connection</param>
    ///
    public void releaseConnection(Connection conxn) {
        lock (this) 
        { 
            conxn.next = connectionChain;
            connectionChain = conxn;
            conxn.commit();
        }
    }

    /// <summary>
    /// Physically close all opened connections
    /// </summary>
    /// 
    public void close() { 
        lock (this) 
        { 
            for (Connection conxn = connectionChain; conxn != null; conxn = conxn.next) 
            {
                conxn.pool = null;
                conxn.close();
            }
            connectionChain = null;
        }
    }

    internal Connection connectionChain;
}


}





